Attribute VB_Name = "Species"
' Copyright (c) 2008 Eric Lockard
' eric@sulaadventures.com
' All rights reserved.
'
'Redistribution and use in source and binary forms, with or without
'modification, are permitted provided that:
'
'(1) source code distributions retain the above copyright notice and this
'    paragraph in its entirety,
'(2) distributions including binary code include the above copyright notice and
'    this paragraph in its entirety in the documentation or other materials
'    provided with the distribution, and
'(3) Without the agreement of the author redistribution of this product is only allowed
'    in non commercial terms and non profit distributions.
'
'THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
'WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
'MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

Option Explicit

Public Function FindSpeciesFromBot(num As Integer) As Integer
  Dim i As Integer

  For i = 0 To SimOpts.SpeciesNum - 1
    If SimOpts.Specie(i).Name = rob(num).FName Then
      FindSpeciesFromBot = i
      Exit Function
    End If
  Next i
  
End Function


'Creates new species when individuals are found that differ by mut mutations and have at least genetic distance gen
Public Function ForkSpecies(mut As Integer, gen As Integer, pop As Integer)
Dim n As Integer
Dim i As Integer
Dim X As Integer
Dim j As Integer
Dim age As Long
Dim oldest As Integer

For n = 1 To MaxRobs
  If rob(n).exist And Not rob(n).Corpse Then
    For X = n + 1 To MaxRobs
      If rob(X).exist And Not rob(X).Corpse Then
        If rob(n).FName = rob(X).FName Then
          If BotsHaveCommonAncestor(n, X, mut, gen) Then
            'Do Nothing
          Else
            i = FindSpeciesFromBot(n)
            If SimOpts.Specie(i).population > pop Then
              'Find Oldest bot of same species as bot X
              oldest = 0
              age = 0
              For j = 1 To MaxRobs
                If rob(j).exist And Not rob(j).Corpse And rob(j).FName = rob(X).FName Then
                  If rob(j).age > age Then
                    age = rob(j).age
                    oldest = j
                  End If
                End If
              Next j
              MDIForm1.MakeNewSpeciesFromBot oldest
            End If
          End If
        End If
      End If
    Next X
  End If
Next n
End Function

'Returns true if the bots have a common ancestor fewer than mut mutations back
Public Function BotsHaveCommonAncestor(bot1 As Integer, bot2 As Integer, mut As Integer, gen As Integer) As Boolean
Dim i, j As Long
Dim closestAncestor As Long
Dim sim As Long

  closestAncestor = FindClosestCommonAncestor(bot1, bot2, sim)
  If closestAncestor <> 0 Then
    i = FindGeneticDistance(bot1, bot2, closestAncestor, sim)
    j = FindGenerationalDistance(bot1, bot2, closestAncestor, sim)
    If (i < mut) Or (j < gen) Then
      BotsHaveCommonAncestor = True
    Else
      BotsHaveCommonAncestor = False
    End If
  Else
    BotsHaveCommonAncestor = True ' This is weird, but in the case where there is no common ancestor at all, we return true
  End If
End Function


